package io.jsen.meta.diff.field;

import io.jsen.meta.diff.annotation.parser.CoAnnotation;
import io.jsen.meta.diff.annotation.parser.CoConvert;
import io.jsen.meta.diff.annotation.parser.MetaFieldDefineSupport;
import io.jsen.meta.diff.feature.IndexFeature;
import io.jsen.meta.diff.feature.MetaFeatureContext;
import io.jsen.meta.diff.obj.Convert;
import io.jsen.meta.diff.obj.MetaObject;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

/**
 * 字段的坐标定义
 * MetaFieldDefine + key
 * <p>
 * 普通字段 key = null
 * <p>
 * collection 里面的字段 key为int（索引）
 * <p>
 * map 里面的字段 key
 *
 * @author jsen
 * @date 2021/4/7
 */
@Data
public class MetaField {

    private MetaFieldDefine fieldDefine;
    private Object key;
    private Class<?> trueClass;

    public MetaField(MetaFieldDefine fieldDefine, Object key) {
        this.fieldDefine = fieldDefine;
        this.key = key;
    }

    public MetaField(MetaFieldDefine fieldDefine) {
        this.fieldDefine = fieldDefine;
        this.key = fieldDefine.getField() != null ? fieldDefine.getField().getName() : null;
    }

    @SuppressWarnings("rawtypes")
    public IndexFeature getIndexFeature() {
        CoAnnotation annotation = MetaFieldDefineSupport
                .getMetaFieldAnnotation(getFieldDefine());
        if (annotation == null) {
            return null;
        }
        return MetaFeatureContext.get(annotation.getIndexFeature());
    }

    public boolean isMetaUniqueKey() {
        CoAnnotation annotation = MetaFieldDefineSupport
                .getMetaFieldAnnotation(getFieldDefine());
        if (annotation == null) {
            return false;
        }
        return annotation.isUniqueKey();
    }

    @SuppressWarnings("unchecked")
    public <S extends MetaObject<?, ?>, T> Convert<S, T> getNativeConvert()
            throws InstantiationException, IllegalAccessException {
        CoConvert convert = MetaFieldDefineSupport.getConvert(this);
        if (convert != null) {
            return (Convert<S, T>) convert.getNative();
        }
        return null;
    }

    @SuppressWarnings("rawtypes")
    public Convert getMetaConvert() throws InstantiationException, IllegalAccessException {
        CoConvert convert = MetaFieldDefineSupport.getConvert(this);
        if (convert != null) {
            return convert.getMeta();
        }
        return null;
    }


    public Class<?> getTrueClass() {
        return trueClass;
    }

    public void setTrueClass(Class<?> trueClass) {
        if (this.trueClass == null) {
            this.trueClass = trueClass;
        }
    }

    @Override
    public String toString() {
        CoAnnotation annotation = MetaFieldDefineSupport
                .getMetaFieldAnnotation(getFieldDefine());
        if (annotation != null && StringUtils.isNotBlank(annotation.getAlias())) {
            return annotation.getAlias();
        }
        return key != null ? key.toString() : fieldDefine.toString();
    }
}
